package com.fuhailiu.opengl.widget;

import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.graphics.Rect;
import android.opengl.GLES30;

import com.fuhailiu.opengl.utils.GlUtil;
import com.fuhailiu.opengl.utils.LogUtil;
import com.fuhailiu.opengl.utils.MatrixUtil;
import com.fuhailiu.opengl.utils.ShaderUtil;
import com.fuhailiu.opengl.view.GLView;

public class GLScissor extends GLView {

	private final String TAG = getClass().getSimpleName();

	private final float x = 0.75f;
	private final float y = 0.75f;

	// 顶点坐标数据
	private float vertices[] = new float[] { 
			-x, -y, 0, // left
			x, -y, 0, // right
			0, y, 0, // top
	};

	// 顶点着色数据
	private float colors[] = new float[] { 
			1, 0, 0, 1, // 红
			0, 1, 0, 1, // 绿
			0, 0, 1, 1, // 蓝
	};

	// 顶点坐标数据缓冲
	private FloatBuffer mBufferVertex;
	// 顶点着色数据缓冲
	private FloatBuffer mBufferColor;

	// 自定义渲染管线程序id
	private int handleProgram;
	// 顶点位置属性引用id
	private int handlePosition;
	// 顶点颜色属性引用id
	private int handleColor;
	// 总变换矩阵引用id
	private int handleMVPMatrix;

	public GLScissor(Context context, int surfaceWidth, int surfaceHeight) {
		super(context);
		setupScissorArea(surfaceWidth, surfaceHeight);
		initVertexData();
		initShader();
	}

	private final float scaleRatio = 0.75f;
	private Rect mRectLarge, mRectMiddle, mRectSmall;

	private void setupScissorArea(int surfaceWidth, int surfaceHeight) {
		LogUtil.LogD(TAG, "setupScissorArea   <---");
		LogUtil.LogD(TAG, "setupScissorArea   surfaceWidth = " + surfaceWidth + ", surfaceHeight = " + surfaceHeight);

		mRectLarge = new Rect(0, 0, surfaceWidth, surfaceHeight);

		int width = (int) (mRectLarge.width() * scaleRatio);
		int height = (int) (mRectLarge.height() * scaleRatio);
		int left = mRectLarge.left + (mRectLarge.width() - width) / 2;
		int top = mRectLarge.top + (mRectLarge.height() - height) / 2;
		mRectMiddle = new Rect(left, top, left + width, top + height);

		width = (int) (mRectMiddle.width() * scaleRatio);
		height = (int) (mRectMiddle.height() * scaleRatio);
		left = mRectMiddle.left + (mRectMiddle.width() - width) / 2;
		top = mRectMiddle.top + (mRectMiddle.height() - height) / 2;
		mRectSmall = new Rect(left, top, left + width, top + height);

		LogUtil.LogD(TAG, "setupScissorArea   --->");
	}

	private void initVertexData() {
		mBufferVertex = GlUtil.createFloatBuffer(vertices);
		mBufferColor = GlUtil.createFloatBuffer(colors);
	}

	private static final String VERTEX_SHADER = 
			"uniform mat4 uMVPMatrix; //总变换矩阵\n" + 
			"attribute vec3 aPosition; //顶点位置\n" + 
			"attribute vec4 aColor; //顶点颜色\n" + 
			"varying vec4 vColor; //用于传递给片元着色器的变量\n" + 
			"void main()\n" + 
			"{\n" + 
			"	gl_Position = uMVPMatrix * vec4(aPosition,1); //根据总变换矩阵计算此次绘制此顶点位置\n" + 
			"	vColor = aColor; //将接收的颜色传递给片元着色器 \n" + 
			"}\n";

	private static final String FRAGMENT_SHADER = 
			"precision mediump float;\n" + 
			"varying vec4 vColor; //接收从顶点着色器过来的参数\n" + 
			"void main()\n" + 
			"{\n" + 
			"	gl_FragColor = vColor; //给此片元颜色值\n" + 
			"}\n";

	private void initShader() {
		LogUtil.LogD(TAG, "initShader   <---");

		// 基于顶点着色器与片元着色器创建程序
		handleProgram = ShaderUtil.createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
		// 获取程序中顶点位置属性引用id
		handlePosition = GLES30.glGetAttribLocation(handleProgram, "aPosition");
		// 获取程序中顶点颜色属性引用id
		handleColor = GLES30.glGetAttribLocation(handleProgram, "aColor");
		// 获取程序中总变换矩阵引用id
		handleMVPMatrix = GLES30.glGetUniformLocation(handleProgram, "uMVPMatrix");

		LogUtil.LogD(TAG, "initShader   --->");
	}

	private final int sizeOfVertexPosition = 3;
	private final int sizeOfVertexColor = 4;

	public void draw(GL10 gl) {
		// enable
		GLES30.glEnable(GLES30.GL_SCISSOR_TEST);

		// large blue window
		GLES30.glClearColor(0, 0, 1.0f, 1.0f);
		GLES30.glScissor(mRectLarge.left, mRectLarge.top, mRectLarge.width(), mRectLarge.height());
		GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);

		// middle red window
		GLES30.glClearColor(1.0f, 0, 0, 1.0f);
		GLES30.glScissor(mRectMiddle.left, mRectMiddle.top, mRectMiddle.width(), mRectMiddle.height());
		GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);

		// small green window
		GLES30.glClearColor(0, 1.0f, 0, 1.0f);
		GLES30.glScissor(mRectSmall.left, mRectSmall.top, mRectSmall.width(), mRectSmall.height());
		GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);

		// 使用shader程序
		GLES30.glUseProgram(handleProgram);
		// 指定顶点位置数据
		GLES30.glVertexAttribPointer(handlePosition, sizeOfVertexPosition, GLES30.GL_FLOAT, false, sizeOfVertexPosition * GlUtil.SIZE_OF_FLOAT, mBufferVertex);
		// 指定顶点颜色数据
		GLES30.glVertexAttribPointer(handleColor, sizeOfVertexColor, GLES30.GL_FLOAT, false, sizeOfVertexColor * GlUtil.SIZE_OF_FLOAT, mBufferColor);
		// 指定变换矩阵
		GLES30.glUniformMatrix4fv(handleMVPMatrix, 1, false, MatrixUtil.getMVPMatrix(), 0);
		// 启用顶点位置数组
		GLES30.glEnableVertexAttribArray(handlePosition);
		// 启用顶点颜色数组
		GLES30.glEnableVertexAttribArray(handleColor);
		// 绘制三角形
		GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, 3);
		// 禁用顶点位置数组
		GLES30.glDisableVertexAttribArray(handleColor);
		// 禁用顶点颜色数组
		GLES30.glDisableVertexAttribArray(handlePosition);

		// disable
		GLES30.glDisable(GLES30.GL_SCISSOR_TEST);

	}

}
